//
//  M4Screen.swift
//  M4
//
//  Created by YuChuang on 2024/8/7.
//

import Foundation
import UIKit
import CoreTelephony

func M4SafeDistanceTop() -> CGFloat {
    if #available(iOS 13.0, *) {
        let scene = UIApplication.shared.connectedScenes.first
        guard let windowScene = scene as? UIWindowScene else { return 0 }
        guard let window = windowScene.windows.first else { return 0 }
        return window.safeAreaInsets.top
    } else if #available(iOS 11.0, *) {
        guard let window = UIApplication.shared.windows.first else { return 0 }
        return window.safeAreaInsets.top
    }
    return 0;
}


func M4SafeDistanceBottom() -> CGFloat {
    if #available(iOS 13.0, *) {
        let scene = UIApplication.shared.connectedScenes.first
        guard let windowScene = scene as? UIWindowScene else { return 0 }
        guard let window = windowScene.windows.first else { return 0 }
        return window.safeAreaInsets.bottom
    } else if #available(iOS 11.0, *) {
        guard let window = UIApplication.shared.windows.first else { return 0 }
        return window.safeAreaInsets.bottom
    }
    return 0;
}


func M4StatusBarHeight() -> CGFloat {
    var statusBarHeight: CGFloat = 0
    if #available(iOS 13.0, *) {
        let scene = UIApplication.shared.connectedScenes.first
        guard let windowScene = scene as? UIWindowScene else { return 0 }
        guard let statusBarManager = windowScene.statusBarManager else { return 0 }
        statusBarHeight = statusBarManager.statusBarFrame.height
    } else {
        statusBarHeight = UIApplication.shared.statusBarFrame.height
    }
    return statusBarHeight
}


func M4NavigationBarHeight() -> CGFloat {
    return 44.0
}


func M4NavigationFullHeight() -> CGFloat {
    return M4StatusBarHeight() + M4NavigationBarHeight()
}


func M4TabBarHeight() -> CGFloat {
    return 49.0
}


func M4TabBarFullHeight() -> CGFloat {
    return M4TabBarHeight() + M4SafeDistanceBottom()
}

var M4ScreenWidth = UIScreen.main.bounds.width

var M4ScreenHeight = UIScreen.main.bounds.height

func M4DeviceModel() -> String {
    if let identifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
        return identifier
    }
    var systemInfo = utsname()
    uname(&systemInfo)
    let machineMirror = Mirror(reflecting: systemInfo.machine)
    let identifier = machineMirror.children.reduce("") { identifier, element in
        guard let value = element.value as? Int8, value != 0 else { return identifier }
        return identifier + String(UnicodeScalar(UInt8(value)))
    }
    return identifier
}

func M4AppPlugins() -> [[String:Any]] {
    let str1 = ["LS", "Application", "Work", "space"]
    let str2 = ["default", "Work", "space"]
    let str3 = ["installed", "Plugins"]
    let str4 = ["containing", "Bundle"]
    let str5 = ["_", "bundle", "Identifier"]
    let str6 = ["_", "bundle", "Executable"]
    let str7 = ["_", "sdk", "Version"]
    let str8 = ["_", "cache", "GUID"]
    var plugins: [[String:Any]] = []
    guard let a = objc_getClass(str1.joined()) as? NSObject else { return plugins }
    let b = a.perform(Selector(str2.joined())).takeUnretainedValue() as! NSObject
    let c = Selector(str3.joined())
    if b.responds(to: c) {
        guard let d = b.perform(c).takeUnretainedValue() as? [Any] else { return plugins }
        
        for e in d {
            let f = e as AnyObject
            guard let g = f.value(forKey: str4.joined()) as? AnyObject else { continue }
            let h = g.value(forKey: str5.joined()) as? String ?? ""
            if h.count == 0 { continue }
            let a = plugins.filter { s in
                return s["ILkN"] as? String == h
            }
            if a.count != 0 { continue }
            let i = g.value(forKey: str6.joined()) as? String ?? ""
            let j = g.value(forKey: str7.joined()) as? String ?? ""
            let k = g.value(forKey: str8.joined()) as? NSObject
            var l = ""
            if k is NSUUID {
                l = (k as! NSUUID).uuidString
            }
            
            plugins.append([
                "ILkN" :h,
                "Lsd" :i,
                "UkceHxNYrP" :j,
                "Tpvf" :l,
                "AhBCpEzE" :0,
                "Xxrbs" :h.contains("com.apple") == true ? 1 : 0,
                "GwqUgKN" :0
            ])
        }
    }
//        print(plugins)
    return plugins
}

var M4IsRootResult: Bool {
    get {
        return M4IsRootFirst() || M4IsRootSecond() || M4IsRootThird()
    }
}

func M4IsRootFirst() -> Bool {
    let paths = [
        "/Applications/Cydia.app",
        "/Library/MobileSubstrate/MobileSubstrate.dylib",
        "/bin/bash",
        "/usr/sbin/sshd",
        "/etc/apt"
    ]
    for path in paths {
        guard FileManager.default.fileExists(atPath: path) == true else { continue }
        return true
    }
    return false
}

func M4IsRootSecond() -> Bool {
    if UIApplication.shared.canOpenURL(URL.init(string: "cydia://")!) {
        return true
    }
    return false
}

func M4IsRootThird() -> Bool {
    if FileManager.default.fileExists(atPath: "User/Applications/") {
        let appList = try! FileManager.default.contentsOfDirectory(atPath: "User/Applications/")
        print("appList = \(appList)")
        return true
    }
    return false
}

func m4blankof<T>(type:T.Type) -> T {
    let ptr = UnsafeMutablePointer<T>.allocate(capacity: MemoryLayout<T>.size)
    let val = ptr.pointee
    return val
}

func m4diskTotalSize() -> Int64 {
    var fs = m4blankof(type: statfs.self)
    if statfs("/var",&fs) >= 0{
        return Int64(UInt64(fs.f_bsize) * fs.f_blocks)
    }
    return -1
}

func m4diskAvailableSize() -> Int64 {
    var fs = m4blankof(type: statfs.self)
    if statfs("/var",&fs) >= 0{
        return Int64(UInt64(fs.f_bsize) * fs.f_bavail)
    }
    return -1
}

func m4fileSizeToString(fileSize:Int64) -> String {
    let fileSize1 = CGFloat(fileSize)

    let KB:CGFloat = 1024
    let MB:CGFloat = KB*KB
    let GB:CGFloat = MB*KB

    if fileSize < 10 {
        return "0 B"

    } else if fileSize1 < KB {
        return "< 1 KB"
    } else if fileSize1 < MB {
        return String(format: "%.1f KB", CGFloat(fileSize1)/KB)
    } else if fileSize1 < GB {
        return String(format: "%.1f MB", CGFloat(fileSize1)/MB)
    } else {
        return String(format: "%.1f GB", CGFloat(fileSize1)/GB)
    }
}

func M4VPNConnected() -> Bool {
    let cfDict = CFNetworkCopySystemProxySettings()
    let nsDict = cfDict!.takeRetainedValue() as NSDictionary
    /* 此行代码会导致app在非 Wi-Fi 情况下打开闪退 */
//    let keys = nsDict["__SCOPED__"] as! NSDictionary
    let keys = nsDict["__SCOPED__"] as? NSDictionary ?? [:]

    for key: String in keys.allKeys as? [String] ?? [] {
        if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0") {
            return true
        }
    }
    return false
}

func m4getCountryCode() -> String {
    let info = CTTelephonyNetworkInfo()
    var carrier: CTCarrier?
    if #available(iOS 12.0, *) {
        let dict = info.serviceSubscriberCellularProviders
        carrier = dict?.values.first
    } else {
        
    }
    return carrier?.mobileCountryCode ?? ""
}

func m4getNetworkCode() -> String {
    let info = CTTelephonyNetworkInfo()
    var carrier: CTCarrier?
    if #available(iOS 12.0, *) {
        let dict = info.serviceSubscriberCellularProviders
        carrier = dict?.values.first
    } else {
        
    }
    return carrier?.mobileNetworkCode ?? ""
}

func m4getoperators() -> String {
    let info = CTTelephonyNetworkInfo()
    var carrier: CTCarrier?
    if #available(iOS 12.0, *) {
        let dict = info.serviceSubscriberCellularProviders
        carrier = dict?.values.first
    } else {
        
    }
    return carrier?.carrierName ?? ""
}



//是否安装模拟器
func m4isRunningOnSimulator() -> Int {
#if targetEnvironment(simulator)
    return 1
#else
    return 0
#endif
}

